package com.code.translate.plugins;

import com.code.translate.function.TextTranslatePlugin;
import com.code.translate.utils.*;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ggh
 * @date 2022/7/17
 * <p>
 * 有道翻译
 */
public class YoudaoTranslatePlugin extends TextTranslatePlugin {
    private final static String indexUrl = "https://fanyi.youdao.com/";
    private final static String translateUrl = "https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule";
    private final static String refer = "https://fanyi.youdao.com/";

    private final static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36";
    private final static Integer signleTranslateTextLen = 5000;

    private static YoudaoTranslatePlugin singleton = new YoudaoTranslatePlugin();

    private YoudaoTranslatePlugin() {
    }

    public static YoudaoTranslatePlugin getSingleton() {
        return singleton;
    }

    @Override
    public Map<String, Object> prepare() throws IOException {
        RequestEntity requestEntity = new RequestEntity(HttpMethod.GET, URI.create(indexUrl));

        ResponseEntity<String> responseEntity = HttpUtils.reqEntity(requestEntity);

        HashMap<String, Object> params = new HashMap<>(1);
        params.put("Cookie", responseEntity.getHeaders().get("Set-Cookie").get(0));
        return params;
    }

    @Override
    public String doTranslate(String text, Map<String, Object> params) throws Exception {
        String response = null;
        Map<String, String> headers = new HashMap<>(3);
        headers.put("User-Agent", UserAgent);
        headers.put("Referer", refer);
        String cookieObj = (String) params.get("Cookie");
        headers.put("Cookie", cookieObj.split(";")[0] + ";___rl__test__cookies=" + System.currentTimeMillis());

        if (text.length() > signleTranslateTextLen) {
            List<String> singleTextList = StringUtils.splitString(text, signleTranslateTextLen, 46);

            Map<String, Object> requestParams = structCommonParams();
            requestParams.put("bv", MD5Utils.md5Hex(headers.get("User-Agent").getBytes()));

            StringBuffer buffer = new StringBuffer();
            for (String singleText : singleTextList) {
                loadTextParams(requestParams, singleText);

                response = HttpUtils.req(translateUrl, HttpMethod.POST, headers, requestParams);
                buffer.append(doExtract(response));
            }
            return buffer.toString();
        } else {
            Map<String, Object> requestParams = structParams(text);
            requestParams.put("bv", MD5Utils.md5Hex(headers.get("User-Agent").getBytes()));

            response = HttpUtils.req(translateUrl, HttpMethod.POST, headers, requestParams);

            return doExtract(response);
        }
    }

    @Override
    protected String doExtract(String response) {
        if (response.contains("\"errorCode\":0")) {
            return JsonpathUtils.read(response, "$.translateResult[*][0].tgt");
        } else {
            System.out.println(response);
            return null;
        }
    }

    private static Map<String, Object> structParams(String text) throws Exception {
        Map<String, Object> params = new HashMap<>(13);

        params.put("from", "en");
        params.put("to", "zh-CHS");
        params.put("smartresult", "dict");
        params.put("client", "fanyideskweb");

        String lts = String.valueOf(System.currentTimeMillis());
        String salt = lts + (RandomUtils.nextInt(9));
        String sign = MD5Utils.md5Hex(("fanyideskweb" + text + salt + "Ygy_4c=r#e#4EX^NUGUc5").getBytes());

        params.put("salt", salt);
        params.put("sign", sign);
        params.put("lts", lts);
        params.put("doctype", "json");
        params.put("version", "2.1");
        params.put("keyfrom", "fanyi.web");
        params.put("action", "FY_BY_REALTlME");
        params.put("i", URLEncoder.encode(text, "utf-8"));

        return params;
    }

    private static Map<String, Object> structCommonParams() {
        Map<String, Object> params = new HashMap<>(13);
        params.put("from", "en");
        params.put("to", "zh-CHS");
        params.put("smartresult", "dict");
        params.put("client", "fanyideskweb");

        String lts = String.valueOf(System.currentTimeMillis());
        String salt = lts + (RandomUtils.nextInt(9));

        params.put("salt", salt);
        params.put("lts", lts);
        params.put("doctype", "json");
        params.put("version", "2.1");
        params.put("keyfrom", "fanyi.web");
        params.put("action", "FY_BY_REALTlME");

        return params;
    }

    private static Map<String, Object> loadTextParams(Map<String, Object> params, String text) throws Exception {
        String sign = MD5Utils.md5Hex(("fanyideskweb" + text + params.get("salt") + "Ygy_4c=r#e#4EX^NUGUc5").getBytes());

        params.put("i", URLEncoder.encode(text, "utf-8"));
        params.put("sign", sign);

        return params;
    }
}
